home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d22 / csap208b.arc / SORTDIR.C < prev    next >
Text File  |  1989-10-10  |  10KB  |  341 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <dos.h>
  5. #include <ctype.h>
  6. #include <mem.h>
  7.  
  8. #include "dosstruc.h"
  9.  
  10. /*
  11.  * SORTDIR is the main routine of CSAP.  It is a recursive routine that will
  12.  * walk the directory hierarchy, sorting all directories that it finds.  It
  13.  * uses the quick sort or quicker sort algorithm provided by most C runtime
  14.  * libraries to perform the actual sort.  It uses DOS Int 25H and 26H,
  15.  * Absolute Disk Read and Absolute Disk Write, to read the directories into
  16.  * memory for sorting and to write out the sorted directories.  It depends
  17.  * upon information about the physical characteristics of the disk provided
  18.  * by GETDPB.
  19.  */
  20.  
  21. void SortDir () {
  22.     void        PutQueue(), GetKey(), qsort();
  23.     void        ReadSub(), WriteSub(), ReadRoot(), WriteRoot();
  24.     char        *strrspn();
  25.     int         strincmp(), SearchFirst();
  26.     unsigned    al2sec(), NextCl();
  27.  
  28.     extern char      Disk, *Fat, Parent[67], Element[13];
  29.     extern char      Line[80], Level, RSwt, VerSwt, Packed;
  30.     extern struct    DpbStruct Dpb;
  31.     extern struct    DirEntry *DirBuff;
  32.     extern unsigned  Cluster, Sector, NumSec;
  33.     extern int         Lim, j, l;
  34.     extern struct    ClusterEntry *p, *t;
  35.     extern int       OutSectors, OutClusters, BytesPerCluster, ECount;
  36.     extern struct    ExtFcb Fcb;
  37.     extern struct    ExtendedEntry Dir;
  38.     extern struct    ClusterQueue CluQ;
  39.     extern int       Is12Bit, *CluArray;
  40.     extern unsigned  MinMem;
  41.  
  42.     char      **DirVector, *r, Reply;
  43.     int       i, k, DirCount, Root;
  44.     unsigned  Mem;
  45.  
  46.  
  47.     BytesPerCluster = (Dpb.ClusterSize + 1) * Dpb.SectorSize;
  48.  
  49.     if (strlen(Element) != 0) {  /* Sorting a sub-directory */
  50.         Root = 0;
  51.         bdos(0x3B, (int) Parent, 0);             /* Set Current Directory */
  52.         if (Parent[strlen(Parent)-1] != '\\') strcat(Parent, "\\");
  53.         setdta((char *) &Dir);
  54.         parsfnm(Element, (struct fcb *) &Fcb.DriveId, 0);
  55.         Fcb.FcbHdr.Header = 0xFF;
  56.         Fcb.DriveId = Disk - '@';
  57.         Fcb.FcbHdr.Attrib = 0xFF;
  58.         if (SearchFirst(&Fcb) != 0) {
  59.             fprintf(stderr, "Not found: %s%s\n", Parent, Element);
  60.             AbortProgram();
  61.             }
  62.         }
  63.     else Root = 1;                /* Sorting the Root directory */
  64.  
  65.     printf("Sorting: %s%s", Parent, Element);
  66.     if (!isdevice(1)) fprintf(stderr, "Sorting: %s%s", Parent, Element);
  67.  
  68. /* Read directory to be sorted into memory */
  69.  
  70.     if (Root) ReadRoot();
  71.     else ReadSub();
  72.  
  73. /* Count sub-directories, skipping "current" and "parent" entries */
  74.  
  75.     for (DirCount=0, i=0; i < Lim / sizeof(struct DirEntry); i++) {
  76.         if (DirBuff[i].Name[0] == 0) break;
  77.         if ((DirBuff[i].Attribute & 0x10)
  78.               && (DirBuff[i].Name[0] != '.')
  79.               && (DirBuff[i].Name[0] != 0xE5)) DirCount++;
  80.         }
  81.     k = i;
  82.     if (DirCount != 0) {
  83.         if ((DirVector = malloc(DirCount * sizeof(DirVector))) == NULL) {
  84.             fprintf(stderr, "Insufficient memory (2).\n");
  85.             return;
  86.             }
  87.         }
  88.  
  89. /*
  90.  * Compute the number of directory sectors to write out - don't write sectors
  91.  * that don't contain active entries.
  92.  */
  93.  
  94.     OutSectors = ((i * 32) + Dpb.SectorSize - 1) / Dpb.SectorSize;
  95.     OutClusters = (OutSectors + Dpb.ClusterSize) >> Dpb.ClusterShift;
  96.  
  97.     j = 0;
  98.     if (Root) {
  99.  
  100. /* If sorting Root - skip 1st two files if "System" & "Hidden" */
  101.  
  102.         if (i > 1) {
  103.             if (DirBuff[j].Attribute & 0x06) {
  104.                 j++; i--;
  105.                 if (DirBuff[j].Attribute & 0x06) {
  106.                     j++; i--;
  107.                     }
  108.                 }
  109.             }
  110.         }
  111.     else {
  112.  
  113. /* If sorting subdirectory - skip 1st two entries, "current" and "parent" */
  114.  
  115.         j += 2; i -= 2;
  116.         }
  117.     if (i == 0) {
  118.         printf(" Empty.\n");
  119.         r = &Parent[strlen(Parent)-1];
  120.         if (r[-1] == ':') r++;
  121.         *r = 0x00;
  122.         return;
  123.         }
  124.  
  125. /* If VerSwt ON - request operator confirmation BEFORE sorting */
  126.  
  127.     if (VerSwt != 0) {
  128.         if (!isdevice(1)) {
  129.             fprintf(stderr, "   Sort (Y or N)? "); fflush(stderr);
  130.             }
  131.         else {
  132.             printf("   Sort (Y or N)? "); fflush(stdout);
  133.             }
  134.         if (toupper(getche()) != 'Y') {
  135.             if (!isdevice(1)) fprintf(stderr, "n");
  136.             printf("\n");
  137.             return;
  138.             }
  139.         }
  140.  
  141.     if (!isdevice(1)) fprintf(stderr, "\n");
  142.     printf("\n");
  143.  
  144. /* Sort directory */
  145.  
  146.     qsort(&DirBuff[j], i, sizeof(struct DirEntry), strincmp);
  147.  
  148.     ECount = 0;
  149.  
  150. /*
  151.  * If Packed OFF, remove "erased" entries from directory (mark them "unused)
  152.  */
  153.  
  154.     if (Packed != 0) {
  155.         for (i=k; i >= 0; i--) {
  156.             if ((DirBuff[i].Name[0] != 0xE5) && (DirBuff[i].Name[0] != 0x00)) break;
  157.             if (DirBuff[i].Name[0] == 0xE5) {
  158.                 DirBuff[i].Name[0] = 0x00;
  159.                 ++ECount;
  160.                 }
  161.             }
  162.         }
  163.  
  164. /* Build list of subdirectories - skipping "current" and "parent" entries */
  165.  
  166.     for (l=0, i=0; DirBuff[i].Name[0]; i++) {
  167.         if ((DirBuff[i].Attribute & 0x10) && (DirBuff[i].Name[0] != '.')) {
  168.             for (k=0, j=0; j<8; ++j) {
  169.                 if (DirBuff[i].Name[j] == ' ') break;
  170.                 else Line[k++] = DirBuff[i].Name[j];
  171.                 }
  172.             if (DirBuff[i].Ext[0] != ' ') {
  173.                 Line[k++] = '.';
  174.                 for (j=0; j<3; ++j) {
  175.                     if (DirBuff[i].Ext[j] == ' ') break;
  176.                     else Line[k++] = DirBuff[i].Ext[j];
  177.                     }
  178.                 }
  179.             Line[k++] = '\0';
  180.             if ((DirVector[l] = malloc(k)) == NULL) {
  181.                 fprintf(stderr, "Insufficient memory.\n");
  182.                 return;
  183.                 }
  184.             strcpy(DirVector[l++], Line);
  185.             }
  186.         }
  187.  
  188. /* Write out sorted directory */
  189.  
  190.     if (Root) {
  191.         WriteRoot();
  192.         if (RSwt) printf("    Location: %04XH-%04XH\n", Dpb.DirStart, Dpb.DirStart + NumSec - 1);
  193.         }
  194.     else {
  195.         WriteSub();
  196.         if (RSwt) {
  197.             printf("    Location:");
  198.             for (i=0; i<CluQ.Count; ++i) {
  199.                 if (i == 0) printf(" %04XH", Alu2Sec(&Dpb, CluArray[i]));
  200.                 if ((i > 0) && (CluArray[i] != CluArray[i-1] + 1)) {
  201.                     printf("-%04XH %04XH",
  202.                            Alu2Sec(&Dpb, CluArray[i-1] + 1) - 1,
  203.                            Alu2Sec(&Dpb, CluArray[i])
  204.                            );
  205.                     }
  206.                 }
  207.             printf("-%04XH\n", Alu2Sec(&Dpb, CluArray[i-1] + 1) - 1);
  208.             }
  209.         }
  210.     if (RSwt) printf("    %d Erased entries removed\n", ECount);
  211.  
  212.     Mem = coreleft();
  213.     if (MinMem < Mem) MinMem = Mem;
  214.  
  215. /* Release dynamically acquired space for this directory */
  216.  
  217.     free(DirBuff);
  218.     for (p = CluQ.Head; p != NULL; p = t) {
  219.         t = p->Next; free(p);
  220.         }
  221.     free(CluArray);
  222.  
  223. /* If Recursive sort - build Parent and Element for sub directories & sort */
  224.  
  225.     if (!Level) {
  226.         strcat(Parent, Element);
  227.         for (i=0; i < DirCount; i++) {
  228.             strcpy(Element, DirVector[i]);
  229.  
  230.             SortDir();
  231.  
  232.             }
  233.         r = strrspn(Parent, "\\/");
  234.         if (r[-1] == ':') r++;
  235.         *r = 0x00;
  236.         }
  237.     }
  238.  
  239. void ReadSub() {
  240.  
  241.     extern unsigned Cluster;
  242.     extern unsigned  LastCluster;
  243.     extern char *Fat;
  244.     extern struct    ExtendedEntry Dir;
  245.     extern struct    ClusterQueue CluQ;
  246.     extern int       Is12Bit, *CluArray, BytesPerCluster, Lim;
  247.     extern char Disk, *Fat;
  248.     extern struct    DirEntry *DirBuff;
  249.     extern struct    DpbStruct Dpb;
  250.  
  251.     int i;
  252.     struct ClusterEntry *p;
  253.     void PutQueue();
  254.     unsigned NextCl();
  255.  
  256.     Cluster = Dir.Body.FirstCluster;
  257.     CluQ.Head = CluQ.Current = NULL; CluQ.Count = 0;
  258.     while (Cluster < LastCluster) {
  259.         PutQueue(&CluQ, Cluster);
  260.         Cluster = NextCl(Is12Bit, Cluster, Fat);
  261.         }
  262.     if ((CluArray = malloc(CluQ.Count * sizeof(int))) == NULL) {
  263.         fprintf(stderr, "Insufficient memory (3).\n");
  264.         return;
  265.         }
  266.     for (i=0, p=CluQ.Head; p != NULL; i++, p=p->Next) {
  267.         CluArray[i] = p->Cluster;
  268.         }
  269.     Lim = CluQ.Count * BytesPerCluster;
  270.     if ((DirBuff = malloc(Lim)) == NULL) {
  271.         fprintf(stderr, "Insufficient memory for directory buffer.\n");
  272.         return;
  273.         }
  274.     for (i=0; i < CluQ.Count; i++) {
  275.         if (absread(Disk-'A', Dpb.ClusterSize + 1,
  276.                           Alu2Sec(&Dpb, CluArray[i]),
  277.                           (char *) &DirBuff[(i * BytesPerCluster) / 32])) {
  278.             fprintf(stderr, "Error reading directory.\n"); exit(1);
  279.             }
  280.         }
  281.     }
  282.  
  283. void WriteSub () {
  284.  
  285.     extern struct    ClusterQueue CluQ;
  286.     extern char      Disk, *Fat, Parent[67], Element[13];
  287.     extern struct    DpbStruct Dpb;
  288.     extern int       Is12Bit, *CluArray, BytesPerCluster;
  289.     extern struct    DirEntry *DirBuff;
  290.  
  291.     int i;
  292.  
  293.     for (i=0; i < CluQ.Count; i++) {
  294.         if (abswrite(Disk-'A', Dpb.ClusterSize + 1,
  295.                            Alu2Sec(&Dpb, CluArray[i]),
  296.                            (char *) &DirBuff[(i * BytesPerCluster) / 32])) {
  297.             fprintf(stderr, "Error writing directory.\n"); exit(1);
  298.             }
  299.         }
  300.     }
  301.  
  302. void ReadRoot () {
  303.  
  304.     extern struct    DpbStruct Dpb;
  305.     extern unsigned  NumSec;
  306.     extern struct    DirEntry *DirBuff;
  307.     extern int       Is12Bit, *CluArray, Lim;
  308.     extern char      Disk;
  309.  
  310.     int i;
  311.     int Error;
  312.  
  313.     Lim = Dpb.MaxEntries * 32;
  314.     NumSec = (Lim + Dpb.SectorSize - 1) / Dpb.SectorSize;
  315.     if ((DirBuff = malloc(Lim)) == NULL) {
  316.         fprintf(stderr, "Insufficient memory for cluster buffer.\n");
  317.         return;
  318.         }
  319.     if ((CluArray = malloc(sizeof(int))) == NULL) {
  320.         fprintf(stderr, "Insufficient memory (4).\n");
  321.         return;
  322.         }
  323.     CluArray[0] = 0;
  324.     if ((Error = absread(Disk-'A', NumSec, Dpb.DirStart, (char *) DirBuff)) != 0) {
  325.         fprintf(stderr, "Error reading root:  %04X.\n", Error); exit(1);
  326.         }
  327.     }
  328.  
  329.  
  330. void WriteRoot () {
  331.  
  332.     extern char Disk;
  333.     extern unsigned  Cluster, Sector, NumSec;
  334.     extern struct    DpbStruct Dpb;
  335.     extern struct    DirEntry *DirBuff;
  336.  
  337.     if (abswrite(Disk-'A', NumSec, Dpb.DirStart, (char *) DirBuff)) {
  338.         fprintf(stderr, "Error writing Root.\n"); exit(1);
  339.         }
  340.     }
  341.